<template>
  <div class="page" v-loading="loading" element-loading-text="加载中...">
    <div class="group_3">
      <!-- 任务基本信息卡片 -->
      <div class="info-card">
        <div class="info-header">
          <div class="left-section">
            <h1 class="job-title">{{ job.title || "任务标题" }}</h1>
            <div class="tag-container">
              <el-tag
                  v-for="(tag, index) in processedTags"
                  :key="index"
                  size="medium"
                  effect="plain"
                  class="mr-2"
              >
                {{ tag }}
              </el-tag>
            </div>
            <div class="basic-info">
              <div class="info-item">
                <i class="el-icon-money"></i>
                <span class="reward">{{ job.money || 0 }}r/题</span>
              </div>

              <div class="info-item">
                <i class="el-icon-user"></i>
                <span
                >已报名: {{ job.joinedPeople || 0 }}/{{
                    job.totalParticipants || 1
                  }}</span
                >
              </div>
              <div class="info-item">
                <i class="el-icon-time"></i>
                <span>截止日期：{{ formattedEndTime }}</span>
              </div>
              <div class="info-item">
                <i class="el-icon-s-operation"></i>
                <span
                >{{ job.groupCount || 1 }}组 ×
                  {{ job.groupSize || 1 }}人</span
                >
              </div>
              <div class="info-item" v-if="job.enableAI">
                <i class="el-icon-cpu"></i>

                <span class="ai-info">
                  {{ job.aiMode === "internal" ? "内置AI" : "外置AI" }}
                  <el-tag
                      size="mini"
                      :type="job.useMirror ? 'warning' : 'info'"
                      class="ai-tag"
                  >
                    {{ job.useMirror ? "镜像" : "普通" }}
                  </el-tag>
                </span>
              </div>
            </div>
          </div>
          <div class="right-section">
            <img :src="backgroundImage" class="job-image" alt="任务图片"/>
          </div>
        </div>

        <!-- 添加任务描述区域 -->
        <div class="description-section">
          <div class="section-header">
            <div class="section-title">
              <div class="title-bar"></div>
              <h2>基本要求</h2>
            </div>
          </div>
          <div class="description-content">
            <!-- 使用 Quill 只读视图展示内容 -->
            <div class="ql-container ql-snow" style="border: none">
              <div
                  class="ql-editor"
                  v-html="job.description || '暂无描述'"
              ></div>
            </div>
          </div>
          <!-- 添加报名按钮 -->
          <div class="join-button-container">
            <el-button
                type="primary"
                size="large"
                class="join-button"
                :disabled="isJoined || job.joinedPeople >= job.totalParticipants"
                @click="handleJoin"
            >
              {{ getJoinButtonText }}
            </el-button>
          </div>
        </div>

        <el-alert
            v-if="job.notice"
            :title="job.notice"
            type="warning"
            :closable="false"
            show-icon
            class="mt-4"
        />
      </div>

      <!-- 文件共享区域前，新增任务文件栏 -->
      <div v-if="isJoined && job.fileUrl" class="task-file-container">
        <div class="section-header">
          <div class="section-title">
            <div class="title-bar"></div>
            <h2>任务文件</h2>
          </div>
        </div>
        <el-table :data="[taskFileRow]" style="width: 100%" :header-cell-style="{ background: '#f5f7fa' }" border>
          <el-table-column prop="fileName" label="文件名" min-width="200">
            <template #default="{ row }">
              <div class="file-name-cell">
                <i class="el-icon-document"/>
                <span>{{ row.fileName }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="180" fixed="right">
            <template #default="{ row }">
              <el-button
                  type="text"
                  icon="el-icon-download"
                  @click="handleDownloadTaskFile(row)"
              >下载
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- 文件共享区域 -->
      <div v-if="isJoined" class="file-sharing-container">
        <div class="section-header">
          <div class="section-title">
            <div class="title-bar"></div>
            <h2>文件共享</h2>
          </div>
          <el-upload
              class="upload-button"
              action=""
              :auto-upload="false"
              :on-change="handleFileChange"
              :limit="5"
              multiple
          >
            <el-button type="primary" icon="el-icon-upload2"
            >上传文件
            </el-button
            >
            <template #tip>
              <div class="el-upload__tip">
                支持任意格式文件，单个文件不超过10MB
              </div>
            </template>
          </el-upload>
        </div>

        <el-table
            :data="sharedFiles"
            style="width: 100%"
            :header-cell-style="{ background: '#f5f7fa' }"
            border
        >
          <el-table-column prop="fileName" label="文件名" min-width="200">
            <template #default="{ row }">
              <div class="file-name-cell">
                <i class="el-icon-document"/>
                <span>{{ row.fileName }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="uploadTime" label="上传时间" width="180"/>
          <el-table-column prop="uploader" label="上传者" width="120"/>
          <el-table-column prop="fileSize" label="文件大小" width="120"/>
          <el-table-column label="操作" width="180" fixed="right">
            <template #default="{ row }">
              <el-button
                  type="text"
                  icon="el-icon-download"
                  @click="handleDownload(row)"
              >
                下载
              </el-button>
              <el-button
                  type="text"
                  icon="el-icon-delete"
                  class="delete-button"
                  @click="handleDeleteFile(row)"
              >
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <!-- 工作区域 -->
      <div v-if="isJoined" class="workspace-container">
        <div class="control-bar">
          <div class="ai-select">
            <span class="assistant-label">AI 协同:</span>
            <!-- <el-select v-model="assistant_value" class="assistant-select">
              <el-option
                v-for="item in assistant_options"
                :key="item.value"
                :value="item.value"
                :label="item.label"
              /> 
            </el-select>
           -->
          </div>
          <div class="size-controls">
            <el-button-group>
              <el-button size="small" @click="handleReset">重置</el-button>
              <el-button size="small" @click="handleLeft">展开左侧</el-button>
              <el-button size="small" @click="handleRight">展开右侧</el-button>
            </el-button-group>
          </div>
        </div>

        <div class="workspace-content">
          <!-- 编辑器区域 -->
          <div class="editor-section" :style="{ flex: `${leftDivWidth} 1 0%` }">
            <div class="editor-wrapper">
              <div class="editor-header">
                <span class="editor-title">任务提交</span>
                <div class="editor-actions">
                  <el-button
                      v-if="hasSubmission"
                      type="text"
                      size="small"
                      @click="handleDeleteSubmission"
                  >
                    <i class="el-icon-delete"></i>
                    删除提交
                  </el-button>
                </div>
              </div>
              <div ref="quillEditor" class="quill-editor"></div>
              <div class="submit-button-container">
                <el-button
                    type="primary"
                    size="large"
                    class="submit-button"
                    :loading="submitting"
                    @click="handleSubmit"
                >
                  <i class="el-icon-check"></i>
                  {{ hasSubmission ? '更新提交' : '提交任务' }}
                </el-button>
              </div>
            </div>
          </div>

          <!-- 聊天区域 -->
          <div class="chat-section" :style="{ flex: `${rightDivWidth} 1 0%` }">
            <div class="chat-header">
              <h3 class="chat-title">
                {{ groupName || "聊天区域" }} ({{ formatGroupMembers }})
              </h3>
            </div>
            <div class="messages-container" ref="messageContainer">
              <div
                  v-for="(message, index) in sortedMessages"
                  :key="message.messageId"
                  :class="getMessageClass(message)"
              >
                <div class="avatar-container">
                  <img
                      :src="getMessageAvatar(message)"
                      :alt="getMessageSenderName(message)"
                      class="avatar"
                  />
                  <span class="sender-name">{{
                      getMessageSenderName(message)
                    }}</span>
                </div>
                <div class="message-bubble">
                  <span
                      v-if="message.messageType === 1"
                      class="message-type-tag"
                  >
                    @消息
                  </span>
                  <span
                      v-if="message.messageType === 2"
                      class="message-type-tag"
                  >
                    AI回复
                  </span>
                  <div class="message-content">{{ message.content }}</div>
                  <div class="message-time">
                    {{ formatMessageTime(message.created_at) }}
                  </div>
                </div>
              </div>
            </div>
            <div class="input-area">
              <div class="input-controls">
                <el-button
                    size="small"
                    :type="isAtQwenMode ? 'primary' : 'default'"
                    @click="toggleAtQwen"
                    :disabled="job.enableAI !== 1"
                >
                  @Qwen
                </el-button>
                <el-button
                    size="small"
                    :type="isAtDeepSeekMode ? 'primary' : 'default'"
                    @click="toggleAtDeepSeek"
                    :disabled="job.enableAI !== 1"
                >
                  @DeepSeek R1
                </el-button>
                <el-button
                    size="small"
                    :type="isAtDeepSeekV3Mode ? 'primary' : 'default'"
                    @click="toggleAtDeepSeekV3"
                    :disabled="job.enableAI !== 1"
                >
                  @DeepSeek V3
                </el-button>
                <el-button
                    size="small"
                    :type="isAtDouBaoMode ? 'primary' : 'default'"
                    @click="toggleAtDouBao"
                    :disabled="job.enableAI !== 1"
                >
                  @豆包
                </el-button>
              </div>
              <el-input
                  ref="messageInput"
                  v-model="newMessage"
                  placeholder="输入消息... 在AI协作模式下，点击@Qwen或@DeepSeek R1来询问AI助手"
                  :rows="3"
                  type="textarea"
                  @keyup.enter.native="sendMessage"
              />
              <el-button
                  type="primary"
                  @click="sendMessage"
                  :disabled="!newMessage.trim()"
              >
                发送
              </el-button>
            </div>
          </div>
        </div>
      </div>

      <!-- 未报名时显示提示 -->
      <div v-else class="workspace-placeholder">
        <el-empty description="报名参加任务后即可开始工作" :image-size="200">
          <el-button
              type="primary"
              @click="handleJoin"
              :disabled="isJoined || job.joinedPeople >= job.totalParticipants"
          >
            {{ getJoinButtonText }}
          </el-button>
        </el-empty>
      </div>

      <!-- 当前共享文件区域 -->
      <div v-if="job.file_url" class="current-file-card">
        <div class="current-file-header">
          <i class="el-icon-document"></i>
          <span class="current-file-title">当前共享文件：</span>
          <span class="current-file-name">{{ getFileName(job.file_url) }}</span>
          <el-button
              type="primary"
              size="mini"
              icon="el-icon-download"
              @click="downloadJobFile"
              class="current-file-download"
          >下载
          </el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Quill from "quill";
import "quill/dist/quill.snow.css";
import {Client} from "@stomp/stompjs";
import config from "@/config";
import {
  fetchConversations,
  joinJob,
  fetchGroupChatMessages,
  sendGroupChatMessage,
  fetchJobGroupId,
  fetchGroupName,
  fetchJobDataWithStatus,
  fetchGroupMembers,
  uploadGroupFile,
  deleteGroupFile,
  fetchGroupFiles,
  deleteSubmission,
  getUserSubmission,
  submitUserContent,
} from "@/api/api";
import {getUserId, getToken, getUsername} from "@/api/auth";
import {mapGetters} from "vuex";
import axios from "axios";

export default {
  components: {},
  data() {
    return {
      submitting: false,
      jobId: null,
      groupId: null,
      groupName: "",
      groupMembers: [], // 群组成员列表
      groupMembersTotal: 0, // 群组成员总数
      groupMembersPagination: {
        current: 1,
        size: 10,
        total: 0
      },
      // WebSocket客户端
      stompClient: null,
      // AI助手选项配置
      assistant_options: [
        // {
        //   value: "0",
        //   label: "不协作",
        // },
        // {
        //   value: "1",
        //   label: "外置协作",
        // },
        // {
        //   value: "2",
        //   label: "内置协作",
        // },
      ],
      leftDivWidth: 50,
      rightDivWidth: 50,
      containerHeight: 369,
      editorHeight: 329,
      assistant_value: "0",
      job: {}, // 活动详情数据
      conversations: [],
      messages: [],
      newMessage: "",
      concurrentConversationId: null,
      isJoined: false,
      loading: false,
      backgroundImage: "",
      imageLoadError: false,
      userAvatar: require("@/assets/images/default-avatar.jpg"), // 添加默认用户头像
      aiAvatar: require("@/assets/images/default-avatar.jpg"), // 添加默认AI头像
      quill: null, // 添加 quill 实例引用
      isQuillInitialized: false, // 添加标记，记录编辑器是否已初始化
      isAtQwenMode: false, // 添加@qwen模式标记
      isAtDeepSeekMode: false, // 添加@DeepSeek模式标记
      isAtDeepSeekV3Mode: false, // 添加@DeepSeek V3模式标记
      isAtDouBaoMode: false, // 添加@豆包模式标记
      modelType: 1, // 默认使用千问模型
      sharedFiles: [], // 共享文件列表
      fileListTimer: null, // 添加定时器引用
      fileListRefreshInterval: 5000, // 刷新间隔，默认 5 秒
      submission: null,
      hasSubmission: false,
      taskFileRow: {}, // 任务主文件行
    };
  },

  watch: {
    $route: {
      immediate: true,
      handler(to) {
        const newJobId = to.params.id || to.query.id;
        if (newJobId && newJobId !== this.jobId) {
          // 如果路由中的jobId变化了，更新本地jobId并重新获取数据
          this.jobId = newJobId;
          localStorage.setItem("current_job_id", this.jobId);
          this.fetchJobData();
        }
      },
    },
    "job.imageSrc": {
      handler() {
        this.loadBackgroundImage();
      },
      immediate: true,
    },
    isJoined: {
      immediate: true,
      handler(newVal) {
        if (newVal) {
          // 确保 DOM 已更新
          this.$nextTick(() => {
            this.initQuillEditor();
          });
        }
      },
    },
    assistant_value(newVal) {
      // 当切换到AI协作模式时，自动加载最新消息
      if (newVal !== "0") {
        this.loadMessages();
      }
      // 保存UI设置
      this.saveUISettings();
    },
    modelType(newVal) {
      // 当模型类型变化时，保存UI设置
      this.saveUISettings();
    },
    job: {
      handler(newJob) {
        // 每次任务详情变化时，更新任务文件行
        if (newJob && newJob.fileUrl) {
          this.taskFileRow = {
            fileName: this.getFileName(newJob.fileUrl),
            fileUrl: newJob.fileUrl
          };
        } else {
          this.taskFileRow = {};
        }
      },
      immediate: true,
      deep: true
    },
  },

  methods: {
    // 重置左右区域宽度为默认值
    handleReset() {
      this.leftDivWidth = 50;
      this.rightDivWidth = 50;
      this.saveUISettings();
    },

    // 展开左侧区域
    handleLeft() {
      this.leftDivWidth = 80;
      this.rightDivWidth = 20;
      this.saveUISettings();
    },

    // 展开右侧区域
    handleRight() {
      this.leftDivWidth = 20;
      this.rightDivWidth = 80;
      this.saveUISettings();
    },

    // 保存UI设置到localStorage
    saveUISettings() {
      if (this.jobId) {
        const settings = {
          leftDivWidth: this.leftDivWidth,
          rightDivWidth: this.rightDivWidth,
          assistant_value: this.assistant_value,
          modelType: this.modelType,
        };
        const key = `job_ui_${this.jobId}`;
        localStorage.setItem(key, JSON.stringify(settings));
        console.log("UI设置已保存到localStorage，键名:", key);
      }
    },

    // 从localStorage恢复UI设置
    restoreUISettings() {
      if (this.jobId) {
        try {
          const key = `job_ui_${this.jobId}`;
          const savedSettings = localStorage.getItem(key);
          if (savedSettings) {
            const settings = JSON.parse(savedSettings);
            this.leftDivWidth = settings.leftDivWidth || 50;
            this.rightDivWidth = settings.rightDivWidth || 50;
            this.assistant_value = settings.assistant_value || "0";
            this.modelType = settings.modelType || 1;
            console.log("已从localStorage恢复UI设置，键名:", key);
          }
        } catch (error) {
          console.error("恢复UI设置失败:", error);
        }
      }
    },

    // 更新容器和编辑器高度
    updateHeights() {
      const parentHeight = this.$refs.parentContainer?.offsetHeight;
      if (parentHeight) {
        this.containerHeight = parentHeight;
        this.editorHeight = parentHeight - 80; // 减去上下padding
      }
    },

    // 根据内容动态调整编辑器高度
    adjustHeight(initialHeight) {
      const editorContent = this.$refs.quillEditor.querySelector(".ql-editor");
      if (editorContent) {
        const delta = this.quill.getContents();
        let contentHeight = initialHeight;

        // 计算文本和图片内容的总高度
        delta.ops.forEach((op) => {
          if (typeof op.insert === "string") {
            const lines = op.insert.split("\n").length - 1;
            contentHeight += lines * 20; // 每行文本高度
          } else if (op.insert.image) {
            contentHeight += 350; // 图片默认高度
          }
        });

        this.editorHeight = contentHeight;
        this.containerHeight = contentHeight + 80;
      }
    },
    async getConversationList() {
      try {
        // 检查是否已登录
        const token = localStorage.getItem("token");
        if (!token) {
          console.log("用户未登录，跳过获取对话列表");
          return;
        }

        const conversations = await fetchConversations();
        if (!conversations || conversations.length === 0) {
          console.log("暂无对话列表");
          return;
        }

        this.conversations = conversations;
        console.log("对话列表:", conversations);

        if (this.conversations.length > 0) {
          // 获取第一个对话的消息列表
          await this.loadMessages(this.conversations[0].id);
          this.concurrentConversationId = this.conversations[0].id;
          console.log("conversationId:", this.concurrentConversationId);
        }
      } catch (error) {
        // 只有在真正的错误时才显示错误信息
        if (error.response && error.response.status !== 400) {
          console.error("获取对话列表失败:", error);
        }
      }
    },

    async loadMessages() {
      try {
        if (!this.groupId) {
          console.log("无效的群组ID");
          return;
        }

        const messages = await fetchGroupChatMessages(this.groupId);
        console.log("完整的消息数据:", messages);
        this.messages = messages;

        // 保存消息到localStorage
        this.saveMessages();

        // 确保在消息更新后滚动到底部
        this.$nextTick(() => {
          this.scrollToBottom();
        });
      } catch (error) {
        this.$message.error("获取消息失败");
        console.error("获取消息失败:", error);
      }
    },

    // 保存消息到localStorage
    saveMessages() {
      if (this.messages && this.messages.length > 0 && this.jobId) {
        const key = `job_messages_${this.jobId}`;
        localStorage.setItem(key, JSON.stringify(this.messages));
        console.log("聊天消息已保存到localStorage，键名:", key);
      }
    },

    // 从localStorage恢复消息
    restoreMessages() {
      if (this.jobId) {
        try {
          const key = `job_messages_${this.jobId}`;
          const savedMessages = localStorage.getItem(key);
          if (savedMessages) {
            this.messages = JSON.parse(savedMessages);
            console.log("已从localStorage恢复聊天消息，键名:", key);

            // 确保在消息恢复后滚动到底部
            this.$nextTick(() => {
              this.scrollToBottom();
            });
          }
        } catch (error) {
          console.error("恢复聊天消息失败:", error);
        }
      }
    },

    // 切换@qwen模式
    toggleAtQwen() {
      this.isAtQwenMode = !this.isAtQwenMode;
      if (this.isAtQwenMode) {
        this.isAtDeepSeekMode = false; // 关闭DeepSeek模式
        this.modelType = 1; // 设置为千问模型
        this.newMessage = "@qwen " + this.newMessage;
        this.$refs.messageInput.focus();
      }
    },

    // 切换@DeepSeek模式
    toggleAtDeepSeek() {
      this.isAtDeepSeekMode = !this.isAtDeepSeekMode;
      if (this.isAtDeepSeekMode) {
        this.isAtQwenMode = false; // 关闭Qwen模式
        this.isAtDeepSeekV3Mode = false; // 关闭DeepSeek V3模式
        this.modelType = 2; // 设置为DeepSeek R1模型
        this.newMessage = "@DeepSeek R1 " + this.newMessage;
        this.$refs.messageInput.focus();
      }
    },

    // 切换@DeepSeek V3模式
    toggleAtDeepSeekV3() {
      this.isAtDeepSeekV3Mode = !this.isAtDeepSeekV3Mode;
      if (this.isAtDeepSeekV3Mode) {
        this.isAtQwenMode = false; // 关闭Qwen模式
        this.isAtDeepSeekMode = false; // 关闭DeepSeek R1模式
        this.modelType = 3; // 设置为DeepSeek V3模型
        this.newMessage = "@DeepSeek V3 " + this.newMessage;
        this.$refs.messageInput.focus();
      }
    },

    // 切换@豆包模式
    toggleAtDouBao() {
      this.isAtDouBaoMode = !this.isAtDouBaoMode;
      if (this.isAtDouBaoMode) {
        this.isAtQwenMode = false; // 关闭Qwen模式
        this.isAtDeepSeekMode = false; // 关闭DeepSeek R1模式
        this.isAtDeepSeekV3Mode = false; // 关闭DeepSeek V3模式
        this.modelType = 4; // 设置为豆包模型
        this.newMessage = "@豆包 " + this.newMessage;
        this.$refs.messageInput.focus();
      }
    },

    async sendMessage() {
      if (!this.newMessage.trim()) return;

      const isAtQwen = this.isAtQwenMode ||
          this.newMessage.toLowerCase().includes('@qwen') ||
          this.isAtDeepSeekMode ||
          this.newMessage.toLowerCase().includes('@deepseek') ||
          this.isAtDeepSeekV3Mode ||
          this.newMessage.toLowerCase().includes('@deepseek v3') ||
          this.isAtDouBaoMode ||
          this.newMessage.toLowerCase().includes('@豆包');

      // 保存消息内容并立即清空输入框
      const messageContent = this.newMessage;
      this.newMessage = '';
      this.isAtQwenMode = false;
      this.isAtDeepSeekMode = false;
      this.isAtDeepSeekV3Mode = false;
      this.isAtDouBaoMode = false;

      try {
        const response = await sendGroupChatMessage(
            this.groupId,
            messageContent,
            isAtQwen,
            this.modelType
        );

        await this.loadMessages();

        // 保存消息到localStorage
        this.saveMessages();

        // 确保在消息发送后滚动到底部
        this.$nextTick(() => {
          this.scrollToBottom();
        });

      } catch (error) {
        // 改进错误处理逻辑
        let errorMessage = '发送消息失败';

        if (error.response) {
          // 有服务器响应的错误
          const status = error.response.status;
          const serverMessage = error.response.data?.message;

          switch (status) {
            case 400:
              errorMessage = serverMessage || '请求参数错误';
              break;
            case 401:
              errorMessage = '请先登录';
              break;
            case 403:
              errorMessage = '没有发送消息的权限';
              break;
            case 404:
              errorMessage = '群组不存在';
              break;
            case 500:
              errorMessage = '服务器内部错误';
              break;
            default:
              errorMessage = serverMessage || '发送消息失败';
          }
        } else if (error.request) {
          // 请求发出但没有收到响应
          errorMessage = '网络连接失败，请检查网络';
        } else {
          // 请求设置时出错
          errorMessage = error.message || '发送消息时出现错误';
        }

        // 移除控制台错误输出
        // console.error('发送消息失败:', error);

        this.$message.error(errorMessage);

        // 如果发送失败，恢复消息内容到输入框
        this.newMessage = messageContent;
      }
    },
    getMessageClass(message) {
      const classes = ["message-wrapper"];
      const currentUserId = getUserId();

      if (message.user_id === "qwen") {
        classes.push("message-ai");
      } else if (message.user_id === currentUserId) {
        classes.push("message-user");
      } else {
        classes.push("message-other");
      }
      return classes;
    },

    getMessageAvatar(message) {
      const currentUserId = getUserId();

      if (message.user_id === "qwen") {
        return this.aiAvatar;
      } else {
        let avatarUrl = message.profile_picture_url;
        if (avatarUrl && avatarUrl.startsWith("https://")) {
          avatarUrl = "http://" + avatarUrl.substring(8);
        }
        return avatarUrl || require("@/assets/images/default-avatar.jpg");
      }
    },

    getMessageSenderName(message) {
      const currentUserId = getUserId();

      if (!message || !message.user_id) {
        return "未知用户";
      }

      // 确保进行字符串比较
      const messageUserId = String(message.user_id);
      const currentUserIdStr = String(currentUserId);

      if (messageUserId === "qwen") {
        return "AI助手";
      } else if (messageUserId === currentUserIdStr) {
        return "我";
      } else {
        return message.username || `用户${messageUserId}`;
      }
    },

    async handleJoin() {
      try {
        console.log("开始报名操作");
        this.loading = true;
        const response = await joinJob(this.jobId);

        console.log("报名响应:", response);

        // 更新本地状态
        this.isJoined = true;
        this.job.joinedPeople += 1;

        // 保存报名状态到localStorage
        localStorage.setItem(`job_joined_${this.jobId}`, JSON.stringify(true));

        // 获取群组ID
        await this.fetchGroupId();

        // 显示成功消息
        this.$message.success(response || "报名成功！");

        // 平滑滚动到工作区
        this.$nextTick(() => {
          const workspaceEl = document.querySelector(".workspace-container");
          if (workspaceEl) {
            workspaceEl.scrollIntoView({behavior: "smooth"});
            // 初始化编辑器
            this.initQuillEditor();
          }
        });
      } catch (error) {
        // 显示错误消息
        this.$message.error(error.message);
        console.log("报名失败:", error);

        // 如果是已经报名的错误，更新本地状态并获取群组ID
        if (error.message.includes("已经报名")) {
          this.isJoined = true;
          // 保存报名状态到localStorage
          localStorage.setItem(
              `job_joined_${this.jobId}`,
              JSON.stringify(true)
          );
          await this.fetchGroupId();
        }
      } finally {
        this.loading = false;
        console.log("报名操作完成");
      }
    },

    // WebSocket相关方法
    initWebSocket() {
      if (this.stompClient) {
        this.disconnectWebSocket();
      }

      const token = getToken();
      if (!token || !this.groupId) {
        console.log("无法初始化WebSocket：缺少token或groupId");
        return;
      }

      // 从代理配置中获取实际的后端地址
      const backendUrl = config.dev.proxyTable["/api"].target;
      const wsUrl = backendUrl.replace("http://", "ws://");
      const fullWsUrl = `${wsUrl}ws`;
      console.log("WebSocket URL:", fullWsUrl);

      this.stompClient = new Client({
        brokerURL: fullWsUrl,
        connectHeaders: {
          Authorization: `Bearer ${token}`,
        },
        debug: (str) => {
          console.log("STOMP Debug:", str);
        },
        onConnect: (frame) => {
          console.log("WebSocket连接成功");

          try {
            // 订阅群组消息
            this.stompClient.subscribe(
                `/topic/group/${this.groupId}`,
                this.onMessageReceived,
                {Authorization: `Bearer ${token}`}
            );

            // 订阅私人消息
            this.stompClient.subscribe(
                "/queue/messages",
                this.onMessageReceived,
                {Authorization: `Bearer ${token}`}
            );
          } catch (error) {
            console.error("订阅消息失败:", error);
          }
        },
        onStompError: (frame) => {
          console.error("STOMP错误:", frame);
        },
      });

      try {
        this.stompClient.activate();
      } catch (error) {
        console.error("WebSocket连接激活失败:", error);
      }
    },

    onMessageReceived(message) {
      try {
        const receivedMessage = JSON.parse(message.body);
        console.log("收到新消息:", receivedMessage);

        // 将新消息添加到消息列表
        this.messages.push(receivedMessage);

        // 保存消息到localStorage
        this.saveMessages();

        // 滚动到底部
        this.$nextTick(() => {
          this.scrollToBottom();
        });
      } catch (error) {
        console.error("处理消息失败:", error);
      }
    },

    disconnectWebSocket() {
      if (this.stompClient) {
        try {
          this.stompClient.deactivate();
          console.log("WebSocket连接已断开");
        } catch (error) {
          console.error("断开WebSocket连接时出错:", error);
        }
      }
    },

    // 修改现有的fetchGroupId方法
    async fetchGroupId() {
      try {
        console.log("开始获取群组ID");
        const groupId = await fetchJobGroupId(this.jobId);
        console.log("获取到群组ID:", groupId, "类型:", typeof groupId);
        this.groupId = groupId;

        // 保存群组ID到localStorage
        localStorage.setItem(`job_group_${this.jobId}`, groupId);

        // 获取群组名称
        await this.fetchGroupName();

        // 获取到群组ID后初始化WebSocket连接
        this.initWebSocket();

        // 先尝试从localStorage恢复消息
        this.restoreMessages();

        // 然后加载最新的历史消息
        await this.loadMessages();

        // 获取群组成员信息
        await this.fetchGroupMembers();

        // 加载文件列表（只加载一次）
        console.log('初始化加载文件列表，当前groupId:', this.groupId);
        await this.loadSharedFiles();

        // 获取到群组ID后加载提交内容
        await this.loadSubmission();
      } catch (error) {
        if (error.message === "未找到相关群组") {
          this.$message.warning("未找到相关群组，无法加载聊天记录");
        } else {
          this.$message.error("获取群组成员失败");
          console.error("获取群组成员失败:", error);
        }
      }
    },

    // 添加获取群组名称的方法
    async fetchGroupName() {
      try {
        if (!this.groupId) {
          console.log("无效的群组ID，无法获取群组名称");
          return;
        }

        console.log("开始获取群组名称");
        const response = await fetchGroupName(this.groupId);
        console.log("获取到群组名称:", response);

        if (response && response.groupName) {
          this.groupName = response.groupName;
          // 保存群组名称到localStorage
          localStorage.setItem(`job_group_name_${this.jobId}`, this.groupName);
        }
      } catch (error) {
        console.error("获取群组名称失败:", error);
        // 失败时使用默认名称，不影响主要功能
        this.groupName = `群组 ${this.groupId}`;
        // 保存默认群组名称到localStorage
        localStorage.setItem(`job_group_name_${this.jobId}`, this.groupName);
      }
    },

    initQuillEditor() {
      // 如果编辑器已经初始化过，直接返回
      if (this.isQuillInitialized) {
        return;
      }

      // 如果已经存在编辑器实例，先移除它
      if (this.quill) {
        this.quill.off();
        if (this.$refs.quillEditor) {
          this.$refs.quillEditor.innerHTML = "";
        }
        this.quill = null;
      }

      if (this.$refs.quillEditor) {
        const toolbarOptions = [
          ["bold", "italic", "underline", "strike"],
          ["blockquote", "code-block"],
          [{header: 1}, {header: 2}],
          [{list: "ordered"}, {list: "bullet"}],
          [{script: "sub"}, {script: "super"}],
          [{indent: "-1"}, {indent: "+1"}],
          [{direction: "rtl"}],
          [{size: ["small", false, "large", "huge"]}],
          [{header: [1, 2, 3, 4, 5, 6, false]}],
          [{color: []}, {background: []}],
          [{font: []}],
          [{align: []}],
          ["clean"],
          ["link", "image"],
        ];

        this.quill = new Quill(this.$refs.quillEditor, {
          modules: {
            toolbar: toolbarOptions,
          },
          theme: "snow",
        });

        // 标记编辑器已初始化
        this.isQuillInitialized = true;

        // 从localStorage恢复编辑器内容
        this.restoreEditorContent();

        // 监听内容变化，动态调整高度并保存内容
        this.quill.on("text-change", () => {
          this.$nextTick(() => {
            this.adjustHeight(329);
            this.saveEditorContent();
          });
        });

        // 在编辑器初始化后加载提交内容
        this.loadSubmission();
      }
    },

    // 保存编辑器内容到localStorage
    saveEditorContent() {
      if (this.quill && this.jobId) {
        const content = this.quill.getContents();
        const key = `job_editor_${this.jobId}`;
        localStorage.setItem(key, JSON.stringify(content));
        console.log("编辑器内容已保存到localStorage，键名:", key);
      }
    },

    // 从localStorage恢复编辑器内容
    restoreEditorContent() {
      if (this.quill && this.jobId) {
        try {
          const key = `job_editor_${this.jobId}`;
          const savedContent = localStorage.getItem(key);
          if (savedContent) {
            const content = JSON.parse(savedContent);
            this.quill.setContents(content);
            console.log("已从localStorage恢复编辑器内容，键名:", key);
          }
        } catch (error) {
          console.error("恢复编辑器内容失败:", error);
        }
      }
    },

    async fetchJobData() {
      try {
        console.log("开始加载任务数据，jobId:", this.jobId);
        this.loading = true;
        const {jobData, joinStatus} = await fetchJobDataWithStatus(
            this.jobId
        );

        console.log("获取到任务数据:", jobData); // <-- 新增调试输出
        console.log("获取到报名状态:", joinStatus);

        this.job = jobData;
        this.isJoined = joinStatus;

        // 如果已经报名，获取群组ID
        if (this.isJoined) {
          await this.fetchGroupId();
        }

        this.loadBackgroundImage();
        this.loading = false;
        console.log("任务数据加载完成");
      } catch (error) {
        console.error("获取数据失败:", error);
        this.$message.error("获取数据失败，请稍后重试");
        this.loading = false;

        // 如果API请求失败，尝试从localStorage恢复基本数据
        this.tryRecoverFromLocalStorage();
      }
    },

    // 尝试从localStorage恢复基本数据
    tryRecoverFromLocalStorage() {
      try {
        // 尝试恢复isJoined状态
        const joinedStatus = localStorage.getItem(`job_joined_${this.jobId}`);
        if (joinedStatus) {
          this.isJoined = JSON.parse(joinedStatus);
          console.log("已从localStorage恢复报名状态:", this.isJoined);
        }

        // 尝试恢复groupId
        const savedGroupId = localStorage.getItem(`job_group_${this.jobId}`);
        if (savedGroupId) {
          this.groupId = savedGroupId;
          console.log("已从localStorage恢复群组ID:", this.groupId);

          // 恢复群组名称
          const savedGroupName = localStorage.getItem(
              `job_group_name_${this.jobId}`
          );
          if (savedGroupName) {
            this.groupName = savedGroupName;
            console.log("已从localStorage恢复群组名称:", this.groupName);
          }

          // 初始化WebSocket
          this.initWebSocket();

          // 恢复消息
          this.restoreMessages();
        }
      } catch (error) {
        console.error("从localStorage恢复数据失败:", error);
      }
    },

    getImageUrl() {
      // 如果有图片链接就使用
      if (this.job.imageSrc && this.job.imageSrc.trim()) {
        return encodeURI(this.job.imageSrc.trim());
      }
      // 否则使用本地默认图片
      return require("@/assets/images/default-king.png");
    },

    loadBackgroundImage() {
      const url = this.getImageUrl().replace("https://", "http://");
      const img = new Image();

      img.onload = () => {
        this.backgroundImage = url;
        this.imageLoadError = false;
      };

      img.onerror = () => {
        console.error("Image load failed:", url);
        this.backgroundImage = require("@/assets/images/default-king.png");
        this.imageLoadError = true;
      };

      img.src = url;
    },

    formatMessageTime(timestamp) {
      if (!timestamp) return "";
      const messageDate = new Date(timestamp);
      const year = messageDate.getFullYear();
      const month = (messageDate.getMonth() + 1).toString().padStart(2, "0");
      const day = messageDate.getDate().toString().padStart(2, "0");
      const hours = messageDate.getHours().toString().padStart(2, "0");
      const minute = messageDate.getMinutes().toString().padStart(2, "0");
      return `${year}年${month}月${day}日 ${hours}:${minute}`;
    },

    // 格式化日期
    formatDate(timestamp) {
      console.log('格式化日期，输入值:', timestamp);
      if (!timestamp) {
        console.log('时间戳为空，返回空字符串');
        return '';
      }
      const fileDate = new Date(timestamp);
      const formatted = `${fileDate.getFullYear()}-${String(fileDate.getMonth() + 1).padStart(2, "0")}-${String(fileDate.getDate()).padStart(2, "0")} ${String(fileDate.getHours()).padStart(2, "0")}:${String(fileDate.getMinutes()).padStart(2, "0")}`;
      console.log('格式化后的日期:', formatted);
      return formatted;
    },

    // 添加滚动到底部的方法
    scrollToBottom() {
      const container = this.$refs.messageContainer;
      if (container) {
        container.scrollTop = container.scrollHeight;
      }
    },

    // 获取群组成员信息
    async fetchGroupMembers() {
      try {
        if (!this.groupId) {
          console.log("无效的群组ID，无法获取成员信息");
          return;
        }

        const response = await fetchGroupMembers(this.groupId);
        console.log("获取到群组成员信息:", response);

        this.groupMembers = response.records || [];
        this.groupMembersTotal = response.total || 0;
        this.groupMembersPagination.total = response.total || 0;

        // 更新localStorage中的群组成员信息
        localStorage.setItem(
            `job_group_members_${this.jobId}`,
            JSON.stringify({
              members: this.groupMembers,
              total: this.groupMembersTotal,
              updateTime: new Date().getTime()
            })
        );
      } catch (error) {
        console.error("获取群组成员失败:", error);
        this.$message.error("获取群组成员信息失败");

        // 尝试从localStorage恢复群组成员信息
        this.tryRecoverGroupMembers();
      }
    },

    // 从localStorage恢复群组成员信息
    tryRecoverGroupMembers() {
      try {
        const savedData = localStorage.getItem(`job_group_members_${this.jobId}`);
        if (savedData) {
          const data = JSON.parse(savedData);
          const updateTime = data.updateTime;
          // 只恢复1小时内的缓存数据
          if (new Date().getTime() - updateTime < 3600000) {
            this.groupMembers = data.members;
            this.groupMembersTotal = data.total;
            console.log("已从localStorage恢复群组成员信息");
          }
        }
      } catch (error) {
        console.error("恢复群组成员信息失败:", error);
      }
    },
    // 处理文件变化
    async handleFileChange(file) {
      console.log('开始上传文件:', file.name);

      // 文件大小检查
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isLt10M) {
        this.$message.error('文件大小不能超过 10MB!');
        return false;
      }

      try {
        // 检查必要参数是否存在
        if (!this.jobId || !this.groupId) {
          this.$message.error('缺少必要参数：任务ID或群组ID');
          return;
        }

        const formData = new FormData();
        // 添加必需参数
        formData.append('file', file.raw);
        formData.append('uploader_name', getUsername());  // 从auth获取用户名
        formData.append('uploader_id', getUserId());      // 从auth获取用户ID
        formData.append('jobId', this.jobId);
        formData.append('groupId', this.groupId);

        // 打印上传参数用于调试
        console.log('上传参数：', {
          fileName: file.name,
          uploader_name: getUsername(),
          uploader_id: getUserId(),
          jobId: this.jobId,
          groupId: this.groupId
        });

        // 显示上传进度提示
        const loadingInstance = this.$loading({
          lock: true,
          text: '正在上传文件...',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });

        console.log('正在上传文件到群组:', this.groupId);
        const response = await uploadGroupFile(formData);
        console.log('文件上传响应:', response);

        loadingInstance.close();
        this.$message.success('文件上传成功');
        await this.loadSharedFiles(); // 刷新文件列表
      } catch (error) {
        console.error('文件上传失败:', error);
        if (error.response) {
          console.error('上传错误详情:', error.response.status, error.response.data);
          this.$message.error(`文件上传失败: ${error.response.data.message || '请重试'}`);
        } else {
          this.$message.error('文件上传失败，请检查网络连接后重试');
        }
      }
    },

    // 处理文件下载
    async handleDownload(file) {
      // 显示下载进度提示
      const loadingInstance = this.$loading({
        lock: true,
        text: '正在下载文件...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });

      try {
        // Directly use file.fileUrl
        const downloadUrl = file.fileUrl;

        // 创建下载链接
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.download = file.fileName;
        // Add target="_blank" and rel="noopener noreferrer" for security and better UX
        link.target = '_blank';
        link.rel = 'noopener noreferrer';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);

        // No need to revoke Blob URL anymore

        loadingInstance.close();
        this.$message.success('文件下载成功');
      } catch (error) {
        loadingInstance.close();
        console.error('文件下载失败:', error);
        if (error.response) {
          this.$message.error(`文件下载失败: ${error.response.data.message || '请重试'}`);
        } else {
          this.$message.error('文件下载失败，请检查网络连接后重试');
        }
      }
    },

    // 处理文件删除
    async handleDeleteFile(file) {
      try {
        await this.$confirm('确定要删除该文件吗？此操作不可恢复', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        });

        // 显示删除进度提示
        const loadingInstance = this.$loading({
          lock: true,
          text: '正在删除文件...',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });

        console.log('删除文件:', file);
        await deleteGroupFile(this.groupId, file.fileId);

        loadingInstance.close();
        this.$message.success('文件删除成功');
        await this.loadSharedFiles(); // 刷新文件列表
      } catch (error) {
        if (error === 'cancel') {
          return;
        }
        console.error('文件删除失败:', error);
        if (error.response) {
          this.$message.error(`文件删除失败: ${error.response.data.message || '请重试'}`);
        } else {
          this.$message.error('文件删除失败，请检查网络连接后重试');
        }
      }
    },

    // 加载共享文件列表
    async loadSharedFiles() {
      console.log('==================== 开始加载文件列表 ====================');
      console.log('当前群组ID:', this.groupId, '类型:', typeof this.groupId);

      try {
        if (!this.groupId) {
          console.warn('未找到有效的群组ID，无法加载文件列表');
          return;
        }

        // 显示加载提示
        const loadingInstance = this.$loading({
          lock: true,
          text: '正在加载文件列表...',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });

        console.log(`正在调用API获取群组(${this.groupId})的文件列表...`);
        const response = await fetchGroupFiles(this.groupId);
        console.log('API响应数据类型:', typeof response);
        console.log('API响应数据结构:', JSON.stringify(response, null, 2));

        // 检查响应数据的结构
        if (response && response.code === 200 && response.data) {
          console.log('检测到标准响应格式 {code: 200, data: ...}');
          // 从分页数据中获取records数组
          const files = response.data.records || [];
          console.log('解析后的文件数组长度:', files.length);
          console.log('文件数组中的groupId值:', files.map(f => f.groupId));

          // 过滤出匹配当前groupId的文件
          const matchedFiles = files.filter(f => String(f.groupId) === String(this.groupId));
          console.log('匹配当前groupId的文件数量:', matchedFiles.length);

          this.sharedFiles = matchedFiles.map(file => {
            console.log('处理文件:', file);
            const processedFile = {
              fileId: file.id,
              fileName: file.fileName,
              uploadTime: this.formatDate(file.uploadTime),
              uploader: file.uploaderName,
              fileSize: this.formatFileSize(file.fileSize),
              fileUrl: file.fileUrl,
              fileType: file.fileType
            };
            console.log('处理后的文件对象:', processedFile);
            return processedFile;
          });

          console.log('最终的文件列表数据:', this.sharedFiles);
          console.log('文件列表长度:', this.sharedFiles.length);
        } else {
          console.warn('API返回的文件列表格式不符合预期:', response);
          console.log('response类型:', typeof response);
          console.log('response属性:', Object.keys(response));
          this.sharedFiles = [];
          this.$message.warning('获取文件列表格式异常，请刷新页面重试');
        }

        loadingInstance.close();
      } catch (error) {
        console.error('加载文件列表时发生错误:', error);
        console.error('错误类型:', error.constructor.name);
        console.error('错误信息:', error.message);
        if (error.response) {
          console.error('服务器响应状态:', error.response.status);
          console.error('服务器响应数据:', error.response.data);
          this.$message.error(`加载文件列表失败: ${error.response.data.message || '请稍后重试'}`);
        } else {
          console.error('完整错误对象:', JSON.stringify(error, Object.getOwnPropertyNames(error)));
          this.$message.error('加载文件列表失败，请检查网络连接后重试');
        }
      }
      console.log('==================== 文件列表加载结束 ====================');
    },

    // 格式化文件大小
    formatFileSize(bytes) {
      console.log('格式化文件大小，输入值:', bytes);
      if (!bytes || bytes === 0) return '0 B';

      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
      console.log('格式化后的大小:', formattedSize);
      return formattedSize;
    },

    // 加载提交内容
    async loadSubmission() {
      try {
        if (!this.jobId || !this.groupId) {
          console.log('缺少必要参数，无法加载提交内容');
          return;
        }

        const response = await getUserSubmission(this.jobId, this.groupId);

        if (response.code === 200 && response.data) {
          this.submission = response.data;
          this.hasSubmission = true;

          // 如果编辑器已初始化，加载内容
          if (this.quill) {
            try {
              const content = JSON.parse(this.submission.content);
              this.quill.setContents(content);
            } catch (error) {
              console.error('解析提交内容失败:', error);
              this.$message.warning('提交内容格式有误，已清空编辑器');
              this.quill.setContents([]);
            }
          }
        } else {
          this.hasSubmission = false;
          this.submission = null;
          if (this.quill) {
            this.quill.setContents([]);
          }
        }
      } catch (error) {
        console.error('加载提交内容失败:', error);
        if (error.response && error.response.status === 404) {
          this.hasSubmission = false;
          this.submission = null;
        } else {
          this.$message.error('加载提交内容失败，请重试');
        }
      }
    },

    // 处理提交
    async handleSubmit() {
      try {
        if (!this.quill) {
          this.$message.warning('编辑器未初始化，请稍后重试');
          return;
        }

        // 检查必要参数
        if (!this.jobId || !this.groupId) {
          console.error('缺少必要参数:', {jobId: this.jobId, groupId: this.groupId});
          this.$message.error('缺少必要参数，请刷新页面重试');
          return;
        }

        // 检查是否登录
        const token = getToken();
        if (!token) {
          this.$message.error('请先登录');
          return;
        }

        this.submitting = true;

        // 获取当前编辑器的新内容
        const newQuillContent = this.quill.getContents();

        // 提交内容
        const response = await submitUserContent(
            this.jobId,
            this.groupId,
            JSON.stringify(newQuillContent)
        );

        if (response.code === 200) {
          this.$message.success('提交成功！');
          // 重新加载提交内容
          await this.loadSubmission();
        }
      } catch (error) {
        console.error('提交失败，详细错误:', error);
        console.error('错误响应:', error.response);

        if (error.response) {
          console.error('错误状态码:', error.response.status);
          console.error('错误数据:', error.response.data);

          switch (error.response.status) {
            case 403:
              this.$message.error('您没有权限提交内容');
              break;
            case 401:
              this.$message.error('请先登录');
              break;
            case 400:
              this.$message.error(error.response.data.message || '请求参数错误');
              break;
            case 404:
              this.$message.error('任务或群组不存在，请检查参数');
              break;
            case 500:
              this.$message.error('服务器内部错误，请稍后重试');
              break;
            default:
              this.$message.error(`提交失败: ${error.response.data.message || '请重试'}`);
          }
        } else if (error.request) {
          console.error('请求错误:', error.request);
          this.$message.error('网络请求失败，请检查网络连接');
        } else {
          console.error('其他错误:', error.message);
          this.$message.error(`提交失败: ${error.message}`);
        }
      } finally {
        this.submitting = false;
      }
    },

    // 删除提交
    async handleDeleteSubmission() {
      try {
        await this.$confirm('确定要删除提交内容吗？此操作不可恢复', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        });

        const response = await deleteSubmission(this.jobId, this.groupId);

        if (response.code === 200) {
          this.submission = null;
          this.hasSubmission = false;
          if (this.quill) {
            this.quill.setContents([]);
          }
          this.$message.success('删除成功');
        }
      } catch (error) {
        if (error === 'cancel') {
          return;
        }
        console.error('删除失败:', error);
        this.$message.error('删除失败，请重试');
      }
    },

    getFileName(url) {
      if (!url) return '未知文件';
      try {
        return decodeURIComponent(url.split('/').pop());
      } catch {
        return url;
      }
    },

    async downloadJobFile() {
      if (!this.job.file_url) {
        this.$message.warning('没有可下载的文件');
        return;
      }
      try {
        const loading = this.$loading({
          lock: true,
          text: '正在下载文件...',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });
        const response = await axios.get(this.job.file_url, {responseType: 'blob'});
        const blob = new Blob([response.data]);
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = this.getFileName(this.job.file_url);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(url);
        loading.close();
        this.$message.success('文件下载成功');
      } catch (error) {
        this.$message.error('文件下载失败，请稍后重试');
      }
    },

    async handleDownloadTaskFile(file) {
      // 将 https:// 替换为 http://
      let url = file.fileUrl;
      if (url.startsWith('https://')) {
        url = 'http://' + url.slice(8);
      }
      const link = document.createElement('a');
      link.href = url;
      link.download = file.fileName;
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      this.$message.success('文件下载请求已发出');
    },
  },
  computed: {
    ...mapGetters(["toDetail"]),
    processedTags() {
      if (!this.job.tags) return ["暂无"];
      return typeof this.job.tags === "string"
          ? this.job.tags.split(",").map((tag) => tag.trim())
          : this.job.tags;
    },
    formattedEndTime() {
      if (!this.job.endTime) return "未知时间";
      const date = new Date(this.job.endTime);
      const year = date.getFullYear();
      const month = (date.getMonth() + 1).toString().padStart(2, "0");
      const day = date.getDate().toString().padStart(2, "0");
      const hour = date.getHours().toString().padStart(2, "0");
      const minute = date.getMinutes().toString().padStart(2, "0");
      return `${year}年${month}月${day}日 ${hour}:${minute}`;
    },
    getJoinButtonText() {
      if (this.isJoined) {
        return "已报名";
      }
      if (this.job.joinedPeople >= this.job.totalParticipants) {
        return "名额已满";
      }
      return "立即报名";
    },
    sortedMessages() {
      return [...this.messages].sort((a, b) => {
        const timeA = new Date(a.created_at).getTime();
        const timeB = new Date(b.created_at).getTime();
        return timeA - timeB;
      });
    },
    // 格式化显示群组成员信息
    formatGroupMembers() {
      if (!this.groupMembers || this.groupMembers.length === 0) {
        return "暂无成员";
      }
      const online = this.groupMembers.filter(member => member.status === "online").length;
      return `${this.groupMembersTotal}人 (${online}人在线)`;
    },

    // 获取群组leader
    groupLeader() {
      return this.groupMembers.find(member => member.role === "leader");
    }
  },
  // 生命周期钩子
  created() {
    // 从路由参数或URL中获取jobId
    this.jobId = this.$route.params.id || this.$route.query.id;

    // 如果没有从路由获取到，尝试从localStorage恢复
    if (!this.jobId) {
      this.jobId = localStorage.getItem("current_job_id");
    }

    if (this.jobId) {
      // 保存当前jobId到localStorage
      localStorage.setItem("current_job_id", this.jobId);

      // 先恢复UI设置
      this.restoreUISettings();
      // 然后获取任务数据
      this.fetchJobData();
    } else {
      this.$message.error("无法获取任务ID，请返回任务列表重新选择");
    }
  },

  mounted() {
    // 确保在mounted中也能获取到正确的jobId
    if (!this.jobId) {
      this.jobId =
          this.$route.params.id ||
          this.$route.query.id ||
          localStorage.getItem("current_job_id");
      if (this.jobId) {
        localStorage.setItem("current_job_id", this.jobId);
        this.fetchJobData();
      }
    }

    // 如果已经加入群组，立即加载一次文件列表
    if (this.isJoined && this.groupId) {
      console.log('组件挂载时加载文件列表');
      this.loadSharedFiles();
    } else {
      console.log('未加入群组或无群组ID，跳过加载文件列表');
    }
  },

  beforeDestroy() {
    // 保存所有数据
    if (this.quill) {
      this.saveEditorContent();
    }
    this.saveMessages();
    this.saveUISettings();

    // 保存报名状态handleFileChange
    if (this.jobId && this.isJoined) {
      localStorage.setItem(
          `job_joined_${this.jobId}`,
          JSON.stringify(this.isJoined)
      );
    }

    // 保存群组信息
    if (this.jobId && this.groupId) {
      localStorage.setItem(`job_group_${this.jobId}`, this.groupId);
      if (this.groupName) {
        localStorage.setItem(`job_group_name_${this.jobId}`, this.groupName);
      }
    }

    // 清理事件监听
    window.removeEventListener("resize", this.updateHeights);
    // 组件销毁前清理编辑器
    if (this.quill) {
      this.quill.off();
      this.quill = null;
      this.isQuillInitialized = false;
    }
    // 断开WebSocket连接
    this.disconnectWebSocket();
  },

  // 修改 activated 和 deactivated 钩子
  activated() {
    if (this.groupId) {
      this.initWebSocket();
    }
  },

  deactivated() {
    this.disconnectWebSocket();
  },
};
</script>

<style scoped lang="css">
.page {
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
  padding: 20px;
}

.group_3 {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 20px;
}

.info-card {
  background: white;
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.file-sharing-container {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 20px;
  margin-top: 20px;
  margin-bottom: 20px;
}

.file-sharing-container .section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.file-sharing-container .section-title {
  display: flex;
  align-items: center;
  gap: 10px;
}

.file-sharing-container .title-bar {
  width: 4px;
  height: 20px;
  background: #409eff;
  border-radius: 2px;
}

.file-sharing-container h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}

.file-sharing-container .upload-button {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.file-sharing-container .el-upload__tip {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.file-name-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.file-name-cell i {
  color: #909399;
  font-size: 16px;
}

.info-header {
  display: flex;
  justify-content: space-between;
  gap: 40px;
}

.left-section {
  flex: 1;
}

.job-title {
  font-size: 28px;
  font-weight: bold;
  color: #303133;
  margin: 0 0 16px 0;
}

.tag-container {
  margin-bottom: 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.basic-info {
  display: flex;
  gap: 24px;
  color: #606266;
  flex-wrap: wrap;
  align-items: center;
}

.info-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
}

.info-item i {
  font-size: 16px;
}

.el-icon-cpu {
  color: #409eff;
}

.el-icon-s-operation {
  color: #67c23a;
}

.ai-info {
  display: flex;
  align-items: center;
  gap: 6px;
}

.ai-tag {
  transform: scale(0.8);
  transform-origin: left center;
}

.reward {
  color: #e6a23c;
  font-weight: bold;
  font-size: 18px;
  font-family: Cera-Bold, sans-serif;
}

.right-section {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 16px;
}

.job-image {
  width: 240px;
  height: 160px;
  object-fit: cover;
  border-radius: 8px;
}

.workspace-container {
  margin-top: 24px;
  background: white;
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  animation: fadeIn 0.5s ease;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.control-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid #ebeef5;
}

.ai-select {
  display: flex;
  align-items: center;
  gap: 12px;
}

.assistant-label {
  font-size: 16px;
  color: #303133;
}

.assistant-select {
  width: 160px;
}

.workspace-content {
  display: flex;
  gap: 20px;
  height: 600px;
}

.editor-section {
  transition: flex 0.3s ease;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
}

.editor-wrapper {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background-color: #f5f7fa;
  border-bottom: 1px solid #ebeef5;
}

.editor-title {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
}

.editor-actions {
  display: flex;
  gap: 8px;
}

.quill-editor {
  flex: 1;
  overflow-y: auto;
}

.chat-section {
  transition: flex 0.3s ease;
  display: flex;
  flex-direction: column;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.chat-header {
  padding: 12px 16px;
  border-bottom: 1px solid #ebeef5;
  background-color: #f5f7fa;
  border-top-left-radius: 4px;
  border-top-right-radius: 4px;
  font-family: Cera-Bold, sans-serif;
}

.chat-title {
  font-size: 16px;
  font-weight: bold;
  color: #303133;
  margin: 0;
  display: flex;
  align-items: center;
}

.messages-container {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  scroll-behavior: smooth;
  background-color: #fff;
}

.message-wrapper {
  display: flex;
  margin-bottom: 20px;
  gap: 12px;
}

.message-user {
  flex-direction: row-reverse;
}

.message-ai,
.message-other {
  flex-direction: row;
}

.avatar-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 40px;
}

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.sender-name {
  font-size: 12px;
  color: #909399;
}

.message-bubble {
  max-width: 70%;
  padding: 12px 16px;
  border-radius: 12px;
  position: relative;
}

.message-user .message-bubble {
  background-color: #409eff;
  margin-right: 8px;
  border-top-right-radius: 4px;
  color: white;
}

.message-user .message-time {
  color: rgba(255, 255, 255, 0.8);
}

.message-user .message-type-tag {
  background-color: rgba(255, 255, 255, 0.2);
  color: white;
}

.message-ai .message-bubble {
  background-color: #f0f9eb;
  margin-left: 8px;
  border-top-left-radius: 4px;
}

.message-other .message-bubble {
  background-color: #f5f5f5;
  margin-left: 8px;
  border-top-left-radius: 4px;
}

.message-content {
  font-size: 14px;
  line-height: 1.5;
  word-break: break-word;
  margin-bottom: 4px;
}

.message-time {
  font-size: 11px;
  color: #909399;
  text-align: right;
}

.message-type-tag {
  position: absolute;
  top: -18px;
  left: 12px;
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 4px;
  background-color: rgba(0, 0, 0, 0.1);
  color: #606266;
}

.input-area {
  padding: 16px;
  border-top: 1px solid #dcdfe6;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.input-controls {
  display: flex;
  gap: 8px;
  align-items: center;
}

.input-area .el-textarea {
  flex: 1;
}

.el-loading-spinner {
  .el-loading-text {
    color: #409eff;
    font-size: 16px;
    margin-top: 10px;
  }
}

/* 添加描述区域样式 */
.description-section {
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid #ebeef5;
}

.section-header {
  margin-bottom: 20px;
}

.section-title {
  display: flex;
  align-items: center;
  gap: 12px;
}

.title-bar {
  width: 4px;
  height: 20px;
  background-color: #e66721;
  border-radius: 2px;
}

.section-title h2 {
  font-size: 20px;
  font-weight: bold;
  color: #303133;
  margin: 0;
}

.description-content {
  padding: 20px;
  background-color: #ffffff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

/* Quill 编辑器内容样式 */
.ql-editor {
  padding: 0;
  min-height: auto;
}

/* 确保 Quill 内容样式正确显示 */
:deep(.ql-editor) {
  font-size: 14px;
  line-height: 1.6;
  color: #606266;
}

:deep(.ql-editor p) {
  margin-bottom: 1em;
}

:deep(.ql-editor h1),
:deep(.ql-editor h2),
:deep(.ql-editor h3) {
  font-weight: 600;
  line-height: 1.4;
  margin: 1em 0 0.5em;
}

:deep(.ql-editor h1) {
  font-size: 1.5em;
}

:deep(.ql-editor h2) {
  font-size: 1.3em;
}

:deep(.ql-editor h3) {
  font-size: 1.1em;
}

:deep(.ql-editor ul),
:deep(.ql-editor ol) {
  padding-left: 1.5em;
  margin-bottom: 1em;
}

:deep(.ql-editor li) {
  margin-bottom: 0.5em;
}

:deep(.ql-editor img) {
  max-width: 100%;
  margin: 1em 0;
  border-radius: 4px;
}

:deep(.ql-editor blockquote) {
  border-left: 4px solid #e6e8eb;
  margin: 1em 0;
  padding-left: 1em;
  color: #909399;
}

:deep(.ql-editor code) {
  background-color: #f5f7fa;
  padding: 0.2em 0.4em;
  border-radius: 3px;
  font-family: Cera-Bold, sans-serif;
}

:deep(.ql-editor pre) {
  background-color: #f5f7fa;
  padding: 1em;
  border-radius: 4px;
  overflow-x: auto;
}

/* 链接样式 */
:deep(.ql-editor a) {
  color: #409eff;
  text-decoration: none;
  transition: color 0.3s ease;
}

:deep(.ql-editor a:hover) {
  color: #66b1ff;
  text-decoration: underline;
}

/* 表格样式 */
:deep(.ql-editor table) {
  border-collapse: collapse;
  width: 100%;
  margin: 1em 0;
}

:deep(.ql-editor td),
:deep(.ql-editor th) {
  padding: 0.5em;
}

:deep(.ql-editor th) {
  background-color: #f5f7fa;
  font-weight: bold;
}

/* 列表样式 */
:deep(.ql-editor ul > li::before) {
  content: "•";
  margin-right: 0.5em;
  color: #909399;
}

:deep(.ql-editor ol) {
  counter-reset: list-counter;
}

:deep(.ql-editor ol > li::before) {
  counter-increment: list-counter;
  content: counter(list-counter) ".";
  margin-right: 0.5em;
  color: #909399;
}

/* 调整工作区域的上边距 */
.workspace-container {
  margin-top: 24px;
}

.join-button {
  min-width: 120px;
  width: 200px;
  height: 40px;
  font-size: 16px;
  font-weight: 500;
}

.join-button:disabled {
  cursor: not-allowed;
}

.join-button-container {
  display: flex;
  justify-content: center;
  margin-top: 24px;
}

.ql-container.ql-snow {
  border: 0px solid #ccc;
}

/* 未报名时的占位样式 */
.workspace-placeholder {
  margin-top: 24px;
  background: white;
  border-radius: 12px;
  padding: 40px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  text-align: center;
}

.delete-button {
  color: #F56C6C;
  margin-left: 10px;
}

.delete-button:hover {
  color: #ff4949;
}

.el-button [class^="el-icon-"] {
  margin-right: 5px;
}

.submit-button-container {
  display: flex;
  justify-content: center;
  padding: 16px;
  background-color: #f5f7fa;
  border-top: 1px solid #ebeef5;
}

.submit-button {
  min-width: 160px;
  height: 44px;
  font-size: 16px;
  font-weight: 500;
  border-radius: 22px;
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
  transition: all 0.3s ease;
  background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
}

.submit-button:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(64, 158, 255, 0.3);
  background: linear-gradient(135deg, #66b1ff 0%, #409eff 100%);
}

.submit-button:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}

.submit-button i {
  margin-right: 8px;
  font-size: 18px;
}

.submit-button.is-loading {
  opacity: 0.8;
  cursor: not-allowed;
  background: #409eff;
}

.current-file-card {
  background: #f9f9f9;
  border-radius: 8px;
  padding: 16px 20px;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
}

.current-file-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.current-file-title {
  font-weight: 500;
  color: #303133;
}

.current-file-name {
  color: #409eff;
  font-weight: 400;
  margin-right: 12px;
}

.current-file-download {
  margin-left: 12px;
}

.task-file-container {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 20px;
  margin-top: 20px;
  margin-bottom: 20px;
}
</style>

